//
//  OBSManager.m
//  Runner
//
//  Created by FXY on 2023/4/8.
//

#import "OBSManager.h"
#import <OBS/OBS.h>

@implementation OBSManager

+ (void)uploadFileWithParams:(NSDictionary *)params result:(FlutterResult)result handler:(StreamHandler *)handler {
    NSString *urlString = [params valueForKey:@"endpoint"];;
    NSString *accessKey = [params valueForKey:@"accessKey"];
    NSString *secretKey = [params valueForKey:@"accessSecret"];
    NSString *bucketName = [params valueForKey:@"bucketName"];
    NSString *objectKey = [params valueForKey:@"objectKey"];
    NSString *filePath = [params valueForKey:@"filePath"];
    NSString *fileId = [params valueForKey:@"fileId"];
    
    if (![urlString containsString:@"http"]) {
        urlString = [NSString stringWithFormat:@"https://%@",urlString];
    }
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 初始化身份验证
        OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:accessKey secretKey:secretKey];
        
        //初始化服务配置
        OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:urlString credentialProvider:credentialProvider];
        
        // 初始化client
        OBSClient *client = [[OBSClient alloc] initWithConfiguration:conf];
        
        // 分段上传的最大并发数
        client.configuration.maxConcurrentUploadRequestCount = 5;
        // 分段上传请求的最大连接数
        client.configuration.uploadSessionConfiguration.HTTPMaximumConnectionsPerHost = 10;
        
        OBSUploadFileRequest *request = [[OBSUploadFileRequest alloc] initWithBucketName:bucketName objectKey:objectKey uploadFilePath:filePath];
        // 分段大小为5MB
        request.partSize = [NSNumber numberWithInteger: 5 * 1024*1024];
        // 开启断点续传模式
        request.enableCheckpoint = YES;
        /// 启动断点续传本地记录
        if ([filePath.pathExtension.lowercaseString isEqualToString:@"mp4"]) {
            NSString *newFilename = [filePath stringByDeletingPathExtension];
            newFilename = [newFilename stringByAppendingPathExtension:@"obsuploadcheckpoint"];
            request.checkpointFilePath = newFilename;
        }
        
        // 上传文件
        request.uploadProgressBlock =  ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
            NSLog(@"%0.1f%%",(float)floor(totalBytesSent*10000/totalBytesExpectedToSend)/100);
            dispatch_async(dispatch_get_main_queue(), ^{
                float progress = (float)floor(totalBytesSent*10000/totalBytesExpectedToSend)/100;
                NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithDictionary:@{@"#@type@#": @"obs",@"progress":[NSString stringWithFormat:@"%lf", progress], @"status":@(1), @"filePath":filePath,@"fileId":fileId}];
                [dic addEntriesFromDictionary:params];
                handler.eventSink(dic);
            });
            
        };
        [OBSManager uploadFile:client request:request params:params handler:handler errorCount:0];
    });
}

+ (void)uploadFile:(OBSClient *)client request:(OBSUploadFileRequest *)request params:(NSDictionary *)params handler:(StreamHandler *)handler errorCount:(NSInteger)errorCount {
    [client uploadFile:request completionHandler:^(OBSUploadFileResponse *response, NSError *error) {
        NSMutableDictionary *returnParams = [[NSMutableDictionary alloc] initWithDictionary:params];
        [returnParams setValue:@"obs" forKey:@"#@type@#"];
        [returnParams setValue:response.requestID forKey:@"requestId"];
        [returnParams setValue:response.statusCode forKey:@"statusCode"];

        if(error) {
            if(errorCount < 10) {
                [OBSManager uploadFile:client request:request params:returnParams handler:handler errorCount:(errorCount + 1)];
            } else {
                [returnParams setValue:@(3) forKey:@"status"];
                [returnParams setValue:error.localizedDescription forKey:@"errorMessage"];
                [returnParams setValue:@{} forKey:@"error"];
                [returnParams setValue:@(error.code) forKey:@"errorCode"];
                dispatch_async(dispatch_get_main_queue(), ^{
                    handler.eventSink(returnParams);
                });
            }
    
        } else {
            if([response.statusCode isEqualToString:@"200"]) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [returnParams setValue:@(2) forKey:@"status"];
                    handler.eventSink( returnParams);
                });
            } else {
                [returnParams setValue:@(3) forKey:@"status"];
                [returnParams setValue:response.statusCode forKey:@"errorMessage"];
                [returnParams setValue:response.statusCode  forKey:@"errorCode"];
                dispatch_async(dispatch_get_main_queue(), ^{
                    handler.eventSink(returnParams);
                });
            }
        }

    }];
    
}

@end
